// Bachelor of Software Engineering 
// Media Design School 
// Auckland
// New Zealand
// 
// (c) 2005 - 2014 Media Design School 
// 
// File Name : main.cpp
// Description : application entry point
// Author : Serge Radinovich
// Mail : srad015@hotmail.com

#include "CardPileGroup.h"
#include "GameObject.h"
#include "Stock.h"
#include "Tableau.h"
#include "Game.h"
#include "Time.h"
#include <time.h>


LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);

HDC hDC;
HCURSOR g_CurrentCursor;
HINSTANCE g_hInstance;
HWND g_hDialogWindow;
HWND g_hMainWindow;
Game* g_pGame = nullptr;
bool g_bMouseDown = false;


const static int SCREEN_WIDTH = static_cast<int>(GetSystemMetrics(SM_CXSCREEN));
const static int SCREEN_HEIGHT = static_cast<int>(GetSystemMetrics(SM_CYSCREEN));
const static int WINDOW_WIDTH = 720;
const static int WINDOW_HEIGHT = 640;

////////////////////////////
//Start or Restart the game
///////////////////////////
void InitializeGame(HWND _hWnd, HINSTANCE _hIstance)
{
	//Also deletes time
	if(g_pGame)
	{
		delete g_pGame;
		g_pGame = 0;
		g_hDialogWindow = NULL; 
		
	}
	g_pGame = Game::CreateGame(_hWnd, _hIstance, hDC);
}

////////////////////////////
//Application entry-point
///////////////////////////
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nShowCmd)
{
	srand(static_cast<int>(time(0)));
	
	g_hInstance = hInstance;
	g_CurrentCursor = LoadCursor(NULL, IDC_ARROW);
	WNDCLASSEX wc;
	MSG msg;
	//HWND hWnd;

	ZeroMemory(&wc, sizeof(WNDCLASSEX));
	
	wc.cbSize = sizeof(WNDCLASSEX);
	wc.style = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc = WindowProc;
	wc.hInstance = hInstance;
	wc.hCursor = g_CurrentCursor;//LoadCursor(NULL, LPCWSTR(_hCursor));
	wc.hbrBackground = (HBRUSH)(GetStockObject(NULL_BRUSH));
	wc.lpszClassName = L"Class1";
	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);//Change these

	//Register and create the window
	RegisterClassEx(&wc);
	HMENU _hMenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU1));
	g_hMainWindow = CreateWindowEx(NULL, L"Class1",
		L"Solitaire",
		WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_VISIBLE,
		SCREEN_WIDTH/2-WINDOW_WIDTH/2, SCREEN_HEIGHT/2-WINDOW_HEIGHT/2,
		WINDOW_WIDTH, WINDOW_HEIGHT,
		NULL,
		_hMenu,
		hInstance,
		NULL);

	if(!g_hMainWindow)
	{
		return 0;
	}
	
	ShowWindow(g_hMainWindow, nShowCmd);

	hDC = GetDC(g_hMainWindow);


	//Game initialization and Loop
	//Time
	InitializeGame(g_hMainWindow, hInstance);

	while(true)
	{
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			
			TranslateMessage(&msg);
			DispatchMessage(&msg);
			if(msg.message == WM_QUIT)
			{				
				delete g_pGame;
				g_pGame = 0;
				break;
			}
		}
		//Game update and draw
		else
		{		
			g_pGame->ExecuteOneFrame();	

			//if game over, display dialogue, exit or InitializeGame and continue
			if(g_pGame->GameOver() && g_hDialogWindow == NULL)
			{
				g_hDialogWindow = CreateDialog(g_hInstance, MAKEINTRESOURCE(IDD_DIALOG1), g_hMainWindow, DialogProc);
				ShowWindow(g_hDialogWindow, SW_SHOW);
			}
		}
		
	}
	return(msg.wParam);
}

////////////////////////////
//Main window procedure
///////////////////////////
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	Vector2 _MousePos;
	//HWND hWndButton;
	

	switch(message)
	{
	
	//Menu buttons
	 case WM_COMMAND: 	
		switch (LOWORD(wParam)) 
        { 
			//Restart
			case ID_FILE_RESTARTGAME:
				InitializeGame(g_hMainWindow, g_hInstance);
				break;
			//Quit game
			case ID_FILE_QUITGAME:
				DestroyWindow(g_hMainWindow);
				break;
			//Credits
			case ID_ABOUT_CREDITS:
				MessageBox(g_hMainWindow, L"Use the left-mouse button to grab cards and push buttons.", L"Controls", NULL);
				break;
		}
		break;
	
		//USER INPUT 
	case WM_LBUTTONDOWN:
	{
		_MousePos.x = LOWORD(lParam);
		_MousePos.y = HIWORD(lParam);
		g_bMouseDown = true;
		g_pGame->MouseClick(_MousePos);
		break;
	}
	
	//MOUSE RELEASED
	case WM_LBUTTONUP:	
	{
		g_bMouseDown = false;
		_MousePos.x = LOWORD(lParam);
		_MousePos.y = HIWORD(lParam);
		g_pGame->MouseRelease(_MousePos);
		break;
	}
	
	//MOUSE MOVING
	case WM_MOUSEMOVE:
	{
		
		if(g_bMouseDown)
		{
			_MousePos.x = LOWORD(lParam);
			_MousePos.y = HIWORD(lParam);
			g_pGame->MoveGrabbedCards(_MousePos);
		}
		break;
	}
	

	case WM_DESTROY:
		{
			ReleaseDC(hWnd, hDC);
			PostQuitMessage(0);
			break;
		
		}
		default:
		{
			return DefWindowProc(hWnd, message, wParam, lParam);
		}

	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}

////////////////////////////
//Procedure for game complete window
///////////////////////////
BOOL CALLBACK DialogProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	int _iScore = 0;
	int _iTime = 0;
	int _iMoves = 0;
	g_pGame->GetScoreTimeAndMoves(_iScore, _iTime, _iMoves); //Grab values to be presented 
	switch (message) 
    { 
		//Set the values
		case WM_INITDIALOG: 
			SetDlgItemInt(hDlg, IDC_SCORE, _iScore, false);
			SetDlgItemInt(hDlg, IDC_TIME, _iTime, false);
			SetDlgItemInt(hDlg, IDC_MOVES, _iMoves, false);
            return TRUE; 
 
		case WM_CLOSE:
			//Closing window restarts the game
			InitializeGame(g_hMainWindow, g_hInstance);
			DestroyWindow(hDlg);
			
			return TRUE;
 
		case WM_DESTROY:
			
			return TRUE;

        case WM_COMMAND: 
 		
			switch (LOWORD(wParam)) 
            { 
			//Quit game
			case IDOK2:
				DestroyWindow(hDlg);
				DestroyWindow(g_hMainWindow);
				return TRUE;
			//Restart game
			case IDOK:
				InitializeGame(g_hMainWindow, g_hInstance);
				DestroyWindow(hDlg);
				return TRUE;
            } 
    } 
    return FALSE; 
}